#include "port/datatype.h"
#include "onps_errors.h"
#include "port/sys_config.h"
#include "port/os_datatype.h"
#include "one_shot_timer.h"
#include "onps_utils.h"
#include "protocols.h"
#include "onps_input.h"
#include "ip/tcp.h"

#if SUPPORT_PPP
#include "ppp/ppp.h"
#endif

#define SYMBOL_GLOBALS
#include "port/os_adapter.h"
#undef SYMBOL_GLOBALS

#if SUPPORT_ETHERNET
//* 系统存在几个网卡局添加几个网卡名称(ETHERNET_NUM宏定义的数量与名称数量应一致)，注意网卡名称不能重名
const CHAR *or_pszaEthName[ETHERNET_NUM] = {
    "eth0"
};
#endif

//* 用户自定义变量声明区
//* ===============================================================================================
#define THOSTIMERCOUNT_STK_SIZE	256

#if SUPPORT_SACK
#define THTCPHANDLER_STK_SIZE 256
#endif

//* ===============================================================================================

//* 定时器任务控制块
static TaskHandle_t l_pstcbTKOneShotTimer;

#if SUPPORT_SACK
//* tcp发送任务控制块
static TaskHandle_t l_pstcbTKTcpHandler;
#endif

//* 协议栈内部工作线程列表
const static STCB_PSTACKTHREAD lr_stcbaPStackThread[] = {
  { thread_one_shot_timer_count, (void *)0, "thread_one_shot_timer_count", THOSTIMERCOUNT_STK_SIZE, THOSTIMERCOUNT_PRIO, &l_pstcbTKOneShotTimer },
  
#if SUPPORT_SACK
  { thread_tcp_handler, (void *)0, "thread_tcp_handler", THTCPHANDLER_STK_SIZE, THTCPHANDLER_PRIO, &l_pstcbTKTcpHandler },
#endif  
}; 

//* 当前线程休眠指定的秒数，参数unSecs指定要休眠的秒数
void os_sleep_secs(UINT unSecs)
{
    vTaskDelay(pdMS_TO_TICKS(unSecs * 1000));
}

//* 当前线程休眠指定的毫秒数，单位：毫秒
void os_sleep_ms(UINT unMSecs)
{
    TickType_t unTicks = pdMS_TO_TICKS(unMSecs);
    unTicks = unTicks ? unTicks : 1;
    vTaskDelay(unTicks);
}

//* 获取系统启动以来已运行的秒数（从0开始）
UINT os_get_system_secs(void)
{
	return HalGetElapsedSecs();
}

//* 获取系统启动以来已运行的毫秒数（从0开始）
UINT os_get_system_msecs(void)
{
    return HalGetElapsedMSecs();
}

void os_thread_onpstack_start(void *pvParam)
{
    BaseType_t nRtnVal;
	
	//* 建立工作线程
	INT i; 
	for (i = 0; i < (INT)(sizeof(lr_stcbaPStackThread) / sizeof(STCB_PSTACKTHREAD)); i++)
	{
	    nRtnVal = xTaskCreate((TaskFunction_t )lr_stcbaPStackThread[i].pfunThread, (const char *)lr_stcbaPStackThread[i].pszTaskName, (USHORT)lr_stcbaPStackThread[i].unStackSize,
	                            lr_stcbaPStackThread[i].pvParam, (UBaseType_t)lr_stcbaPStackThread[i].ubPrio, lr_stcbaPStackThread[i].pstcbTask);
	    if (pdPASS != nRtnVal)
	        printf("The creation of task %s failed, error code: %d\r\n", lr_stcbaPStackThread[i].pszTaskName, nRtnVal);
	}
}

HMUTEX os_thread_mutex_init(void)
{
    HMUTEX hMtx = xSemaphoreCreateMutex();
    if(INVALID_HMUTEX != hMtx)
        return hMtx;
    printf("Mutex lock creation failed, Please check if the memory is enough to allocate.\r\n");
    return INVALID_HMUTEX;
}

void os_thread_mutex_lock(HMUTEX hMutex)
{
    xSemaphoreTake(hMutex, portMAX_DELAY);
}

void os_thread_mutex_unlock(HMUTEX hMutex)
{
    xSemaphoreGive(hMutex);
}

void os_thread_mutex_uninit(HMUTEX hMutex)
{
    vSemaphoreDelete(hMutex);
}

HSEM os_thread_sem_init(UINT unInitVal, UINT unCount)
{
    HSEM hSem = xSemaphoreCreateCounting(unCount, unInitVal);
    if(INVALID_HSEM != hSem)
        return hSem;
    printf("Semaphore creation failed, Please check if the memory is enough to allocate.\r\n");
    return INVALID_HSEM;
}

void os_thread_sem_post(HSEM hSem)
{
    xSemaphoreGive(hSem);
}

INT os_thread_sem_pend(HSEM hSem, INT nWaitSecs)
{
    TickType_t unTicks;
    if(nWaitSecs)
        unTicks = pdMS_TO_TICKS(nWaitSecs * 1000);
    else
        unTicks = portMAX_DELAY;

    BaseType_t nRtnVal = xSemaphoreTake(hSem, unTicks);
    if(pdPASS == nRtnVal)
        return 0;
    else if(pdFAIL == nRtnVal)
        return 1;
    else
        return -1;
}

void os_thread_sem_uninit(HSEM hSem)
{
    vSemaphoreDeleteSafe(hSem);
}

#if SUPPORT_PPP
HTTY os_open_tty(const CHAR *pszTTYName)
{
	pszTTYName = pszTTYName; //* 避免编译器警告
	return 0; 
}

void os_close_tty(HTTY hTTY)
{
	hTTY = hTTY; //* 避免编译器警告
}

INT os_tty_send(HTTY hTTY, UCHAR *pubData, INT nDataLen)
{
	hTTY = hTTY; //* 避免编译器警告
	return 0;
}

INT os_tty_recv(HTTY hTTY, UCHAR *pubRcvBuf, INT nRcvBufLen, INT nWaitSecs)
{
	hTTY = hTTY; //* 避免编译器警告
	return 0; 
}

void os_modem_reset(HTTY hTTY)
{
}
#endif

